package com.zjw.zy.componse.demo.fragment

import android.animation.ValueAnimator
import android.util.Log
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.gestures.*
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.*
import androidx.compose.ui.input.pointer.util.VelocityTracker
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import com.zjw.zy.componse.demo.base.BaseComposeFragment
import com.zjw.zy.componse.demo.ext.shortToast
import com.zjw.zy.componse.demo.ui.theme.MyApplicationTheme
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt

/**
 * @author     ：zhong.jw
 * @date       ：Created in 2023/2/22 8:54
 * @description： 拖拽小球的实现
 */
class BollFragment : BaseComposeFragment() {

    companion object {
        private const val TAG = "BollFragment"
    }

    override fun onContentView(rootView: ComposeView) {
        rootView.setContent {
            MyApplicationTheme {
                BollView()
            }
        }
    }

    override fun onSubscribeValue() {

    }

    /**
     * @return 合法偏移
     * */
    private fun validPositionOffsetChange(
        currentOffsetX: Float,
        currentOffsetY: Float,
        maxOffsetX: Float,
        maxOffsetY: Float,
        positionChange: Offset
    ): Offset {
        val offsetNextX = max(
            0f,
            min(
                maxOffsetX,
                currentOffsetX + positionChange.x
            )
        )
        val offsetNextY = max(
            0f,
            min(
                maxOffsetY,
                currentOffsetY + positionChange.y
            )
        )

        return Offset(offsetNextX, offsetNextY)
    }

    @Composable
    @Preview
    fun BollView() {

        val offset = remember { mutableStateOf(Offset.Zero) }

        val trace = remember {
            VelocityTracker()
        }
        val offsetValueAnimator = remember {
            mutableStateOf<ValueAnimator?>(null)
        }

        Box(modifier = Modifier.fillMaxSize()) {
            Canvas(modifier = Modifier
                .size(50.dp, 50.dp)
                .offset {
                    IntOffset(
                        offset.value.x.roundToInt(), offset.value.y.roundToInt()
                    )
                }
                .pointerInput(Unit) {
                    /**onTouchEvent*/
                    forEachGesture {
                        awaitPointerEventScope {
                            val down = awaitFirstDown(requireUnconsumed = false)
                            offsetValueAnimator.value?.cancel()
                            trace.resetTracking()
                            "开始按下".shortToast()
                            while (true) {
                                val point = awaitPointerEvent().changes[0]

                                //限定范围
                                val positionChange = point.positionChange()
                                offset.value = validPositionOffsetChange(
                                    offset.value.x,
                                    offset.value.y,
                                    requireView().width - 50.dp.toPx(),
                                    requireView().height - 50.dp.toPx(),
                                    positionChange
                                )
                                trace.addPosition(point.uptimeMillis, point.position)
                                point.consume()
                                if (!point.pressed) {
                                    //这是up事件
                                    val v = trace.calculateVelocity()
                                    var vx = v.x
                                    var vy = v.y
                                    if (vx == 0f || vy == 0f) {
                                        return@awaitPointerEventScope
                                    }
                                    //衰减 ms
                                    val decayTime = 5000
                                    var ay = -vy / decayTime
                                    var ax = -vx / decayTime
                                    offsetValueAnimator.value = ValueAnimator
                                        .ofInt(0, decayTime)
                                        .apply {
                                            duration = decayTime.toLong()

                                            addUpdateListener {
                                                val t = it.animatedValue as Int
                                                var lx = 0.0
                                                var ly = 0.0

                                                //附加判断，如果碰到边界，反转速度与加速度
                                                if (offset.value.x >= requireView().width - 50.dp.toPx() || offset.value.x <= 0) {
                                                    Log.d(TAG, "BollView: over-x")
                                                    vx = -vx
                                                    ax = -ax
                                                }
                                                if (offset.value.y >= requireView().height - 50.dp.toPx() || offset.value.y <= 0) {
                                                    Log.d(TAG, "BollView: over-y")
                                                    vy = -vy
                                                    ay = -ay
                                                }

                                                if (t >= 1) {
                                                    //t时刻相对t-1时刻的位移
                                                    lx = -(vx + ax * t - 0.5 * ax)
                                                    ly = -(vy + ay * t - 0.5 * ay)
                                                }
                                                offset.value = validPositionOffsetChange(
                                                    offset.value.x,
                                                    offset.value.y,
                                                    requireView().width - 50.dp.toPx(),
                                                    requireView().height - 50.dp.toPx(),
                                                    Offset(
                                                        lx.toFloat() / 100, ly.toFloat() / 100
                                                    )
                                                )
                                            }
                                            start()
                                        }
                                    break
                                }
                            }
                        }
                    }

                    /**detectDragGestures 实现如下**/
//                    forEachGesture {
//                        awaitPointerEventScope {
//                            val down = awaitFirstDown(requireUnconsumed = false)
//                            var drag: PointerInputChange?
//                            var overSlop = Offset.Zero
//                            do {
//                                //获取一个拖拽事件，
//                                drag = awaitTouchSlopOrCancellation(
//                                    down.id
//                                ) { change, over ->
//                                    //标记被消耗,表示是我们所需要的事件,跳出循环
//                                    change.consume()
//                                    overSlop = over
//                                }
//                            } while (drag != null && !drag.isConsumed)
//
//                            if (drag != null) {
//                                //开始拖拽
//                                trace.resetTracking()
//                                offset.value += overSlop
//
//                                //drag内部是个循环，用户获取到drag事件，返回false表示取消，true表示结束
//                                //所有底层全调用 awaitPointerEvent方法，类似onTouchEvent方法
//                                if (!drag(drag.id) {
//                                        //偏移量，与上一个
//                                        offset.value += it.positionChange()
//                                        it.consume()
//
//                                        //计算速度
//                                        trace.addPosition(it.uptimeMillis, it.position)
//                                    }) {
//
//                                    "拖拽取消".shortToast()
//                                    trace.resetTracking()
//                                } else {
//                                    val v = trace.calculateVelocity()
//                                    v.apply {
//                                        "${this.x} ${this.y}".shortToast()
//                                    }
//                                }
//                            }
//                        }
//                    }

                    /**这是一个高度封装的手势**/
//                    detectDragGestures(onDragStart = {
//                    }, onDragEnd = {
//                    }, onDragCancel = {
//
//                    }, onDrag = { change: PointerInputChange, dragAmount: Offset ->
//                        offset.value += dragAmount
//                    })

                }


            ) {
                drawCircle(Color.Blue)
            }
        }
    }
}